package EP.Clasificador;

import SBD.CRUD.ClasificadorBD;
import Controladores.ControladorJaccard;
import Controladores.ControladorOntologia;
import Controladores.ControladorOperaciones;
import Controladores.ControladorPagina;
import Controladores.ControladorRelacionPagina;
import Controladores.ControladorSimilitudCoseno;
import Controladores.ControladorScore;
import Controladores.ControladorSimilitudEuclidiana;
import EP.Web.Pagina;
import EP.Web.RelacionPaginas;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* @class Clasificador
* @author Mauricio Alvarez.
* @brief Esta clase representa la clase Clasificador, correspondiente a una entidad principal (EP).
*/
public class Clasificador
{

    /**
     *  @var Map<String, Integer> Topico
     *  @brief Variable global Map que representa un tópico de la ontología y su frecuencia.
    */
    private Map<String, Integer> Topico = new HashMap();
    /**
     *  @var Map<String, Integer> Stopwords
     *  @brief Variable global Map que guarda los stopwords.
    */
    private Map<String, Integer> Stopwords = new HashMap<String, Integer>();
    /**
     *  @var List<Pagina> ListaPaginas
     *  @brief Variable global Map que guarda las páginas.
    */
    private List<Pagina> ListaPaginas = new ArrayList<Pagina>();
    /**
     *  @var List<RelacionPaginas> ListaRelacionPaginas
     *  @brief Variable global Map que guarda las relaciones de página (grafo Web).
    */
    private List<RelacionPaginas> ListaRelacionPaginas = new ArrayList<RelacionPaginas>();
    /**
     *  @var Map<Integer, List> ResultadosScore
     *  @brief Variable global Map que guarda los resultados de las métricas de ranking.
    */
    private Map<Integer, List> ResultadosScore = new HashMap();
    /**
     *  @var String Consulta
     *  @brief Almacena la consulta.
    */
    private String Consulta;
    /**
     *  @var ControladorOntologia co
     *  @brief Variable global de tipo clase ControladorOntologia.
    */
    private ControladorOntologia co;
    /**
     *  @var ControladorOperaciones cop
     *  @brief Variable global de tipo clase ControladorOperaciones.
    */
    private ControladorOperaciones cop;
    /**
     *  @var ControladorPagina cpag
     *  @brief Variable global de tipo clase ControladorPagina.
    */
    private ControladorPagina cpag;
    /**
     *  @var ControladorRelacionPagina crelpag
     *  @brief Variable global de tipo clase ControladorRelacionPagina.
    */
    private ControladorRelacionPagina crelpag;
    /**
     *  @var ControladorScore c_score
     *  @brief Variable global de tipo clase ControladorScore.
    */
    private ControladorScore c_score;
    /**
     *  @var ControladorJaccard cj
     *  @brief Variable global de tipo clase ControladorJaccard.
    */
    private ControladorJaccard cj;
    /**
     *  @var ControladorSimilitudCoseno csc
     *  @brief Variable global de tipo clase ControladorSimilitudCoseno.
    */
    private ControladorSimilitudCoseno csc;
    /**
     *  @var ControladorSimilitudEuclidiana cse
     *  @brief Variable global de tipo clase ControladorSimilitudEuclidiana.
    */
    private ControladorSimilitudEuclidiana cse;
    /**
     *  @var  ClasificadorBD cbd
     *  @brief Variable global de tipo clase ClasificadorBD.
    */
    private ClasificadorBD cbd;


    //////////////////////////
    // CONSTRUCTOR
    //////////////////////////
    public Clasificador()
    {
        co = new ControladorOntologia();
        cop = new ControladorOperaciones();
        cpag = new ControladorPagina();
        crelpag = new ControladorRelacionPagina();
        c_score = new ControladorScore();
        cj = new ControladorJaccard();
        csc = new ControladorSimilitudCoseno();
        cse = new ControladorSimilitudEuclidiana();
        cbd = new ClasificadorBD();
    }


    //////////////////////
    // OPERACIONES
    //////////////////////

    /**
     * @brief Invoca las métricas a calcular en base a los parámetros de configuración de las pruebas de filtrado.
     * @param TopicoConsultado, MetricasSeleccionadas, ContenidosSeleccionados, CantidadMuestra, Umbral, Ranking, SeleccionTermino, factorK1 y factorb.
     * @return void
    */
    public void IniciarClasificador(String TopicoConsultado,
                                    ArrayList<Integer> MetricasSeleccionadas,
                                    ArrayList<Integer> ContenidosSeleccionados,
                                    int CantidadMuestra,
                                    double Umbral, 
                                    int Ranking,
                                    boolean SeleccionTermino,
                                    double factorK1,
                                    double factorb,
                                    int N_IDF_DINAMICO) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException, SQLException, FileNotFoundException, Error, Exception
    {

        //Variables para registro del log:
        int config_terminos = 0; //TOPICO
        int config_contenido = 0;//CONTENIDO

        /////////////////////////////////////////////////////////////////
        //PASO 1: Traducir a minusculas y sin acentos la consulta. (OK)
        /////////////////////////////////////////////////////////////////
        Consulta = cop.FormatearConsulta(TopicoConsultado);

        ////////////////////////////////////////////////
        //PASO 2: Se cargan los STOPWORS de la BD (OK)
        ////////////////////////////////////////////////
        Stopwords = cop.CargarStopwords();

        ////////////////////////////////////////////////////////////////////
        //PASO 3: Cargar el topico o sub-arbol ontologico de acuerdo a la
        //        ontologia o considerarla como termino. (OK)
        ////////////////////////////////////////////////////////////////////
        if (SeleccionTermino == true)
        {
            //El topico es equivalente solo a la consulta de entrada:
            Topico = cop.ObtenerPalabrasConsulta(Consulta, Stopwords);
            TopicoConsultado = TopicoConsultado.concat(" (Concepto unico)");
            config_terminos = 1;

        }else{
            //Se obtiene el sub-arbol del tópico:
            //Topico = co.ExtraerConceptosTopico(Consulta);
            TopicoConsultado = TopicoConsultado.concat(" (Tópico)");
            config_terminos = 2;
        }

        //POR BORRAR!!://POR BORRAR!!://POR BORRAR!!://POR BORRAR!!://POR BORRAR!!:
        Set set = Topico.entrySet();

        Iterator i = set.iterator();

        System.out.println("Tamaño del topico: "+ Topico.size());
        while(i.hasNext()){
          Map.Entry me = (Map.Entry)i.next();
          System.out.println("Palabras del topico: "+ me.getKey());
        }
        //POR BORRAR!!://POR BORRAR!!://POR BORRAR!!://POR BORRAR!!://POR BORRAR!!:

 /*
 */
        ////////////////////////////////////////////////////////
        //PASO 4: Se cargan las páginas para el estudio (OK)
        ////////////////////////////////////////////////////////
        ListaPaginas = cpag.CargarPagina(CantidadMuestra);


        //BORRAR ESTO //BORRAR ESTO //BORRAR ESTO //BORRAR ESTO //BORRAR ESTO
        System.out.println(CantidadMuestra+"-------------LISTADO DE PAGINAS-------------------: "+ListaPaginas.size());
        for (int j=0;j<ListaPaginas.size();j++)
        {
            System.out.println("id pagina: "+ ListaPaginas.get(j).getId_pagina());
            System.out.println("host: "+ ListaPaginas.get(j).getHost());
            System.out.println("URL: "+ ListaPaginas.get(j).getUrl());
            System.out.println("Titulo: "+ ListaPaginas.get(j).getTitulo());
            System.out.println("Contenido: "+ ListaPaginas.get(j).getContenido());
            System.out.println("Es semilla: "+ ListaPaginas.get(j).getEs_semilla());
            System.out.println("Nivel grafo: "+ ListaPaginas.get(j).getNivel_grafo());
            System.out.println("--------------------------------");
        }

        //BORRAR ESTO //BORRAR ESTO //BORRAR ESTO //BORRAR ESTO //BORRAR ESTO


        ////////////////////////////////////////////////////////////////////////
        //PASO 5: Se cargan los datos de relación entre las páginas, entre ellas
        //        el surround text: (OK)
        //////////////////////////////////////////////////////////////////////// 
        ListaRelacionPaginas = crelpag.CargarRelacionPagina(CantidadMuestra);

        //BORRAR ESTO //BORRAR ESTO //BORRAR ESTO //BORRAR ESTO //BORRAR ESTO
        System.out.println(CantidadMuestra+"-------------LISTADO DE RELACION PAGINAS-------------------: "+ListaPaginas.size());
        for (int j=0;j<ListaRelacionPaginas.size();j++)
        {
            System.out.println("Id_relacion_pagina: "+ ListaRelacionPaginas.get(j).getId_relacion_pagina());
            System.out.println("pagina_fuente: "+ ListaRelacionPaginas.get(j).getId_pagina_fuente());
            System.out.println("pagina_destino: "+ ListaRelacionPaginas.get(j).getId_pagina_destino());
            System.out.println("Texto_alrededor: "+ ListaRelacionPaginas.get(j).getTexto_alrededor());
            System.out.println("--------------------------------");
        }

        //BORRAR ESTO //BORRAR ESTO //BORRAR ESTO //BORRAR ESTO //BORRAR ESTO



        ////////////////////////////////////////////////////////////////////
        //PASO 6: Se realiza la prueba con los contenidos de las páginas
        //        seleccionadas en la interfaz: BODY y/o SURROUND TEXT
        ////////////////////////////////////////////////////////////////////

        //Se define una variable que determina la opcion escogida para que sea
        //reconocida en el Score: si es body (1), surround text (2) o ambas (3).
        int OpcionContenido;

        //Sólo Body:
        if (ContenidosSeleccionados.get(0)==1 && ContenidosSeleccionados.get(1)==0)
        {
            ////////////////////////////////////////////////////////////////////
            //PASO 7: Se calculan los Scores en todas sus variantes para los
            //        Contenidos de las páginas:
            ////////////////////////////////////////////////////////////////////
            config_contenido = 1;
            OpcionContenido = 1;
            ResultadosScore = c_score.CalcularScore(Topico, Stopwords, ListaPaginas, ListaRelacionPaginas, TopicoConsultado, OpcionContenido, Umbral, Ranking, factorK1, factorb);

            ///////////////////////////////////////////////////////
            //PASO 8: Se calcula segun las métricas seleccionadas
            ///////////////////////////////////////////////////////

            //JACCARD:
            if (MetricasSeleccionadas.get(0) == 1)
            {
                //Se envían los calculos de los scores a JACCARD (OK):
                cj.CalcularJaccard(Topico, ListaPaginas, ListaRelacionPaginas, Stopwords, TopicoConsultado, OpcionContenido, Umbral, Ranking);
            }

            //SIMILITUD COSENO:
            if (MetricasSeleccionadas.get(1) == 1)
            {
                //Se envían los calculos de los scores a la SC (OK):
                csc.CalcularSC(Topico,ResultadosScore, ListaPaginas, ListaRelacionPaginas, Stopwords, TopicoConsultado, OpcionContenido, Umbral, Ranking, N_IDF_DINAMICO);
            }

            //EUCLIDIANA:
            if (MetricasSeleccionadas.get(2) == 1)
            {
                //Se envían los calculos de los scores a la SE (OK):
                cse.CalcularEuclidiana(Topico,ResultadosScore, ListaPaginas, ListaRelacionPaginas, TopicoConsultado, OpcionContenido, Umbral, Ranking);
            }            

            System.out.println("ESTOY AQUI 1");

        }//FIN IF Sólo Body (1)



        //Sólo Predictor:
        if (ContenidosSeleccionados.get(0)==0 && ContenidosSeleccionados.get(1)==1)
        {
            
            ////////////////////////////////////////////////////////////////////
            //PASO 7: Se calculan los Scores en todas sus variantes para los
            //        Surround Text de las páginas (OK).
            ////////////////////////////////////////////////////////////////////
            OpcionContenido = 2;
            config_contenido = 2;
            
            //Descomentar esto luego:
            //ResultadosScore = c_score.CalcularScore(Topico, Stopwords, ListaPaginas, ListaRelacionPaginas, TopicoConsultado, OpcionContenido, Umbral, Ranking, factorK1, factorb);

            ///////////////////////////////////////////////////////
            //PASO 8: Se calcula segun las métricas seleccionadas
            ///////////////////////////////////////////////////////

            //JACCARD:
            if (MetricasSeleccionadas.get(0) == 1)
            {
                //Se envían los calculos de los scores a JACCARD (OK):
                cj.CalcularJaccard(Topico, ListaPaginas, ListaRelacionPaginas, Stopwords, TopicoConsultado, OpcionContenido, Umbral, Ranking);
            }

            //SIMILITUD COSENO:
            if (MetricasSeleccionadas.get(1) == 1)
            {
                //Se envían los calculos de los scores a la SC (OK):
                csc.CalcularSC(Topico,ResultadosScore, ListaPaginas, ListaRelacionPaginas, Stopwords, TopicoConsultado, OpcionContenido, Umbral, Ranking, N_IDF_DINAMICO);
                
            }

            //EUCLIDIANA:
            if (MetricasSeleccionadas.get(2) == 1)
            {
                //Se envían los calculos de los scores a la SE (OK):
                //DESCOMENTAR = cse.CalcularEuclidiana(Topico,ResultadosScore, ListaPaginas, ListaRelacionPaginas, TopicoConsultado, OpcionContenido, Umbral, Ranking);
            }

            
        }//FIN IF Sólo Surround Text (2)



        //Body + Surround Text:
        if (ContenidosSeleccionados.get(0)==1 && ContenidosSeleccionados.get(1)==1)
        {
            ////////////////////////////////////////////////////////////////////
            //PASO 7: Se calculan los Scores en todas sus variantes BODY
            ////////////////////////////////////////////////////////////////////
            config_contenido = 3;
            //BODY:
            OpcionContenido = 1;
            ResultadosScore = c_score.CalcularScore(Topico, Stopwords, ListaPaginas, ListaRelacionPaginas, TopicoConsultado, OpcionContenido, Umbral, Ranking, factorK1, factorb);

            /////////////////////////////////////////////////////////////////
            //PASO 8: Se calcula segun las métricas seleccionadas BODY
            /////////////////////////////////////////////////////////////////

            //JACCARD:
            if (MetricasSeleccionadas.get(0) == 1)
            {
                //Se envían los calculos de los scores a JACCARD (OK):
                cj.CalcularJaccard( Topico, ListaPaginas, ListaRelacionPaginas, Stopwords, TopicoConsultado, OpcionContenido, Umbral, Ranking);
            }

            //SIMILITUD COSENO:
            if (MetricasSeleccionadas.get(1) == 1)
            {
                //Se envían los calculos de los scores a la SC (OK):
                csc.CalcularSC(Topico,ResultadosScore, ListaPaginas, ListaRelacionPaginas, Stopwords, TopicoConsultado, OpcionContenido, Umbral, Ranking, N_IDF_DINAMICO);
            }

            //EUCLIDIANA:
            if (MetricasSeleccionadas.get(2) == 1)
            {
                //Se envían los calculos de los scores a la SE (OK):
                cse.CalcularEuclidiana(Topico,ResultadosScore, ListaPaginas, ListaRelacionPaginas, TopicoConsultado, OpcionContenido, Umbral, Ranking);
            }

            ////////////////////////////////////////////////////////////////////
            //PASO 9: Se calculan los Scores en todas sus variantes ST:
            ////////////////////////////////////////////////////////////////////

            //PREDICTOR:
            OpcionContenido = 2;
            ResultadosScore = c_score.CalcularScore(Topico, Stopwords, ListaPaginas, ListaRelacionPaginas, TopicoConsultado, OpcionContenido, Umbral, Ranking, factorK1, factorb);

            /////////////////////////////////////////////////////////////////
            //PASO 10: Se calcula segun las métricas seleccionadas ST
            /////////////////////////////////////////////////////////////////

            //JACCARD:
            if (MetricasSeleccionadas.get(0) == 1)
            {
                //Se envían los calculos de los scores a JACCARD (OK):
                cj.CalcularJaccard( Topico, ListaPaginas, ListaRelacionPaginas, Stopwords, TopicoConsultado, OpcionContenido, Umbral, Ranking);
            }

            //SIMILITUD COSENO:
            if (MetricasSeleccionadas.get(1) == 1)
            {
                //Se envían los calculos de los scores a la SC (OK):
                csc.CalcularSC(Topico,ResultadosScore, ListaPaginas, ListaRelacionPaginas, Stopwords, TopicoConsultado, OpcionContenido, Umbral, Ranking, N_IDF_DINAMICO);
            }

            //EUCLIDIANA:
            if (MetricasSeleccionadas.get(2) == 1)
            {
                //Se envían los calculos de los scores a la SE (OK):
                cse.CalcularEuclidiana(Topico,ResultadosScore, ListaPaginas, ListaRelacionPaginas, TopicoConsultado, OpcionContenido, Umbral, Ranking);
            }
            
            
            //Se crea el dataset resumen con los datos para el estudio del 
            //Pje. Real vs Predictor:
            
            

            System.out.println(" --- FIN BODY + PREDICTOR ---"); //BORRAR

        }//FIN IF Body + Surround Text (3)


        ////////////////////////////////////////////////////////////////////
        //PASO 11: Se guarda un archivo log de la prueba realizada con las
        //         configuraciones realizadas:
        ////////////////////////////////////////////////////////////////////
        //PASO 1: TOPICO
        //      + NOMBRE TOPICO
        //      + Termino (1) / Topico (2)
        //PASO 2: METRICAS
        //      + Jaccard/Coseno/Euclidiana
        //      + OkapiBM25:
        //          - k1
        //          - b
        //PASO 3: CONFIGURACION CLASIFICADOR
        //      + Umbral
        //      + Ranking
        //      + Contenido: BODY (1), ST (2), BODY+ST (3)
        //PASO 4: CONFIGURAR MUESTRA
        //      + Cantidad o Todas
        cbd.GuardarLogPrueba(TopicoConsultado, config_terminos, config_contenido, MetricasSeleccionadas, factorK1, factorb, Umbral, Ranking, CantidadMuestra);

        
        //Se genera el dataset para el estudio de los pjes. reales vs predictor:
        cbd.GenerarDataset();
        
 /*
 */
        
    }//FIN IniciarClasificador


}//FIN CLASE Clasificador ////////////////////////////////////////////////////////////////////////////////////////